/*
 *          Water.glsl
 *
 *      This is a 'GLSL 4.10 core profile' code.
 */

//------------------------------------------------------------------------------


-- TessControl


/*
  Supposed to be the same that Terrain.glsl so check if it can work
  without problem with it.
*/


--

//------------------------------------------------------------------------------


-- TessEval

// PARAMs
layout(quads) in;
layout(fractional_odd_spacing) in;
layout(cw) in;

// INs
in vec2 tcPosition[];


void main()
{
}

/*
[domain("quad")]
PSIn_Diffuse WaterPatchDS(    PatchData input, 
                              float2 uv : SV_DomainLocation,
                              OutputPatch<DUMMY, 1> inputPatch )
{
    PSIn_Diffuse output;
    float3 vertexPosition;
    float2 texcoord0to1 = (input.origin + uv * input.size)/g_HeightFieldSize;
    float4 water_normal;
    float4 depthmap_scaler;

    // getting rough estimate of water depth from depth map texture 
    depthmap_scaler=g_DepthMapTexture.SampleLevel(SamplerLinearWrap, float2(texcoord0to1.x,1-texcoord0to1.y),0);
    
    // calculating water surface geometry position and normal
    vertexPosition.xz = input.origin + uv * input.size;
    vertexPosition.y  = -g_WaterHeightBumpScale/2;
    water_normal=CombineWaterNormal(vertexPosition.xyz);

    // fading out displacement and normal disturbance near shores by 60%
    water_normal.xyz=lerp(float3(0,1,0),normalize(water_normal.xyz),0.4+0.6*depthmap_scaler.g);
    vertexPosition.y+=water_normal.w*g_WaterHeightBumpScale*(0.4+0.6*depthmap_scaler.g);
    vertexPosition.xz-=(water_normal.xz)*0.5*(0.4+0.6*depthmap_scaler.g);

    // writing output params
    output.position = mul(float4(vertexPosition, 1.0), g_ModelViewProjectionMatrix);
    output.texcoord = texcoord0to1*g_WaterMicroBumpTexcoordScale+g_WaterBumpTexcoordShift*0.07;
    output.normal=normalize(water_normal.xyz);
    output.depthmap_scaler=depthmap_scaler;
    output.positionWS = vertexPosition;
    return output;
}
*/

--

//------------------------------------------------------------------------------


-- Fragment


out vec4 FragColor;

void main()
{
  FragColor = vec4( 1.f );
}

/*
float4 WaterPatchPS(PSIn_Diffuse input) : SV_Target
{
    float4 color;
    float3 pixel_to_light_vector = normalize(g_LightPosition-input.positionWS);
    float3 pixel_to_eye_vector = normalize(g_CameraPosition-input.positionWS);
    float3 reflected_eye_to_pixel_vector;
    float3 microbump_normal; 
    float3x3 normal_rotation_matrix;

    float fresnel_factor;
    float diffuse_factor;
    float specular_factor;
    float scatter_factor;
    float4 refraction_color;
    float4 reflection_color;
    float4 disturbance_eyespace;

    float water_depth;
    float4 water_color;

    // calculating pixel position in light space
    float4 positionLS = mul(float4(input.positionWS,1),g_LightModelViewProjectionMatrix);
    positionLS.xyz/=positionLS.w;
    positionLS.x=(positionLS.x+1)*0.5;
    positionLS.y=(1-positionLS.y)*0.5;

    // calculating shadow multiplier to be applied to diffuse/scatter/specular light components
    float dsf=1.0f/4096.0f;
    float shadow_factor=0.2*g_DepthTexture.SampleCmp(SamplerDepthAnisotropic,positionLS.xy,positionLS.z* 0.995f).r;
    shadow_factor+=0.2*g_DepthTexture.SampleCmp(SamplerDepthAnisotropic,positionLS.xy+float2(dsf,dsf),positionLS.z* 0.995f).r;
    shadow_factor+=0.2*g_DepthTexture.SampleCmp(SamplerDepthAnisotropic,positionLS.xy+float2(-dsf,dsf),positionLS.z* 0.995f).r;
    shadow_factor+=0.2*g_DepthTexture.SampleCmp(SamplerDepthAnisotropic,positionLS.xy+float2(dsf,-dsf),positionLS.z* 0.995f).r;
    shadow_factor+=0.2*g_DepthTexture.SampleCmp(SamplerDepthAnisotropic,positionLS.xy+float2(-dsf,-dsf),positionLS.z* 0.995f).r;

    // need more high frequency bumps for plausible water surface, so creating normal defined by 2 instances of same bump texture
    microbump_normal = normalize(2*g_WaterBumpTexture.Sample(SamplerAnisotropicWrap,input.texcoord-g_WaterBumpTexcoordShift*0.2).gbr - float3 (1,-8,1));
    microbump_normal+= normalize(2*g_WaterBumpTexture.Sample(SamplerAnisotropicWrap,input.texcoord*0.5+g_WaterBumpTexcoordShift*0.05).gbr - float3 (1,-8,1));

    // calculating base normal rotation matrix
    normal_rotation_matrix[1]=input.normal.xyz;
    normal_rotation_matrix[2]=normalize(cross(float3(0.0,0.0,-1.0),normal_rotation_matrix[1]));
    normal_rotation_matrix[0]=normalize(cross(normal_rotation_matrix[2],normal_rotation_matrix[1]));

    // applying base normal rotation matrix to high frequency bump normal
    microbump_normal=mul(normalize(microbump_normal),normal_rotation_matrix);

    
    // simulating scattering/double refraction: light hits the side of wave, travels some distance in water, and leaves wave on the other side
    // it's difficult to do it physically correct without photon mapping/ray tracing, so using simple but plausible emulation below
    
    // only the crests of water waves generate double refracted light
    scatter_factor=2.5*max(0,input.positionWS.y*0.25+0.25);

    // the waves that lie between camera and light projection on water plane generate maximal amount of double refracted light 
    scatter_factor*=shadow_factor*pow(max(0.0,dot(normalize(float3(pixel_to_light_vector.x,0.0,pixel_to_light_vector.z)),-pixel_to_eye_vector)),2.0);
    
    // the slopes of waves that are oriented back to light generate maximal amount of double refracted light 
    scatter_factor*=pow(max(0.0,1.0-dot(pixel_to_light_vector,microbump_normal)),8.0);
    
    // water crests gather more light than lobes, so more light is scattered under the crests
    scatter_factor+=shadow_factor*1.5*g_WaterColorIntensity.y*max(0,input.positionWS.y+1)*
        // the scattered light is best seen if observing direction is normal to slope surface
        max(0,dot(pixel_to_eye_vector,microbump_normal))*
        // fading scattered light out at distance and if viewing direction is vertical to avoid unnatural look
        max(0,1-pixel_to_eye_vector.y)*(300.0/(300+length(g_CameraPosition-input.positionWS)));

    // fading scatter out by 90% near shores so it looks better
    scatter_factor*=0.1+0.9*input.depthmap_scaler.g;

    // calculating fresnel factor 
    float r=(1.2-1.0)/(1.2+1.0);
    fresnel_factor = max(0.0,min(1.0,r+(1.0-r)*pow(1.0-dot(microbump_normal,pixel_to_eye_vector),4)));

    // calculating specular factor
    reflected_eye_to_pixel_vector=-pixel_to_eye_vector+2*dot(pixel_to_eye_vector,microbump_normal)*microbump_normal;
    specular_factor=shadow_factor*fresnel_factor*pow(max(0,dot(pixel_to_light_vector,reflected_eye_to_pixel_vector)),g_WaterSpecularPower);

    // calculating diffuse intensity of water surface itself
    diffuse_factor=g_WaterColorIntensity.x+g_WaterColorIntensity.y*max(0,dot(pixel_to_light_vector,microbump_normal));

    // calculating disturbance which has to be applied to planar reflections/refractions to give plausible results
    disturbance_eyespace=mul(float4(microbump_normal.x,0,microbump_normal.z,0),g_ModelViewMatrix);

    float2 reflection_disturbance=float2(disturbance_eyespace.x,disturbance_eyespace.z)*0.03;
    float2 refraction_disturbance=float2(-disturbance_eyespace.x,disturbance_eyespace.y)*0.05*
        // fading out reflection disturbance at distance so reflection doesn't look noisy at distance
        (20.0/(20+length(g_CameraPosition-input.positionWS)));
    
    // calculating correction that shifts reflection up/down according to water wave Y position
    float4 projected_waveheight = mul(float4(input.positionWS.x,input.positionWS.y,input.positionWS.z,1),g_ModelViewProjectionMatrix);
    float waveheight_correction=-0.5*projected_waveheight.y/projected_waveheight.w;
    projected_waveheight = mul(float4(input.positionWS.x,-0.8,input.positionWS.z,1),g_ModelViewProjectionMatrix);
    waveheight_correction+=0.5*projected_waveheight.y/projected_waveheight.w;
    reflection_disturbance.y=max(-0.15,waveheight_correction+reflection_disturbance.y);

    // picking refraction depth at non-displaced point, need it to scale the refraction texture displacement amount according to water depth
    float refraction_depth=GetRefractionDepth(input.position.xy*g_ScreenSizeInv);
    refraction_depth=g_ZFar*g_ZNear/(g_ZFar-refraction_depth*(g_ZFar-g_ZNear));
    float4 vertex_in_viewspace=mul(float4(input.positionWS,1),g_ModelViewMatrix);
    water_depth=refraction_depth-vertex_in_viewspace.z;
    float nondisplaced_water_depth=water_depth;
    
    // scaling refraction texture displacement amount according to water depth, with some limit
    refraction_disturbance*=min(2,water_depth);

    // picking refraction depth again, now at displaced point, need it to calculate correct water depth
    refraction_depth=GetRefractionDepth(input.position.xy*g_ScreenSizeInv+refraction_disturbance);
    refraction_depth=g_ZFar*g_ZNear/(g_ZFar-refraction_depth*(g_ZFar-g_ZNear));
    vertex_in_viewspace=mul(float4(input.positionWS,1),g_ModelViewMatrix);
    water_depth=refraction_depth-vertex_in_viewspace.z;

    // zeroing displacement for points where displaced position points at geometry which is actually closer to the camera than the water surface
    float conservative_refraction_depth=GetConservativeRefractionDepth(input.position.xy*g_ScreenSizeInv+refraction_disturbance);
    conservative_refraction_depth=g_ZFar*g_ZNear/(g_ZFar-conservative_refraction_depth*(g_ZFar-g_ZNear));
    vertex_in_viewspace=mul(float4(input.positionWS,1),g_ModelViewMatrix);
    float conservative_water_depth=conservative_refraction_depth-vertex_in_viewspace.z;

    if(conservative_water_depth<0)
    {
        refraction_disturbance=0;
        water_depth=nondisplaced_water_depth;
    }
    water_depth=max(0,water_depth);

    // getting reflection and refraction color at disturbed texture coordinates
    reflection_color=g_ReflectionTexture.SampleLevel(SamplerLinearClamp,float2(input.position.x*g_ScreenSizeInv.x,1.0-input.position.y*g_ScreenSizeInv.y)+reflection_disturbance,0);
    refraction_color=g_RefractionTexture.SampleLevel(SamplerLinearClamp,input.position.xy*g_ScreenSizeInv+refraction_disturbance,0);

    // calculating water surface color and applying atmospheric fog to it
    water_color=diffuse_factor*float4(g_WaterDeepColor,1);
    water_color.rgb=lerp(CalculateFogColor(pixel_to_light_vector,pixel_to_eye_vector).rgb,water_color.rgb,min(1,exp(-length(g_CameraPosition-input.positionWS)*g_FogDensity)));
    
    // fading fresnel factor to 0 to soften water surface edges
    fresnel_factor*=min(1,water_depth*5.0);

    // fading refraction color to water color according to distance that refracted ray travels in water 
    refraction_color=lerp(water_color,refraction_color,min(1,1.0*exp(-water_depth/8.0)));
    
    // combining final water color
    color.rgb=lerp(refraction_color.rgb,reflection_color.rgb,fresnel_factor);
    color.rgb+=g_WaterSpecularIntensity*specular_factor*g_WaterSpecularColor*fresnel_factor;
    color.rgb+=g_WaterScatterColor*scatter_factor;
    color.a=1;
    return color;
}
*/

